home *** CD-ROM | disk | FTP | other *** search
/ Visual Cafe 3 / Visual Cafe 3.ISO / Vcafe / Source.bin / SoundPlayer.java < prev    next >
Text File  |  1998-08-27  |  12KB  |  409 lines

  1. package symantec.itools.multimedia;
  2.  
  3. import java.net.URL;
  4. import java.net.URLConnection;
  5. import java.net.MalformedURLException;
  6. import java.io.IOException;
  7. import java.io.InputStream;
  8. import java.util.Enumeration;
  9. import java.util.Vector;
  10. import sun.audio.AudioStream;
  11. import sun.audio.AudioDataStream;
  12. import sun.audio.AudioPlayer;
  13. import sun.audio.AudioData;
  14. import java.beans.PropertyVetoException;
  15. import java.beans.PropertyChangeListener;
  16. import java.beans.VetoableChangeListener;
  17. import java.beans.PropertyChangeEvent;
  18.  
  19. //    06/01/97    TG    Updated to support Java 1.1
  20. //                    Made properties bound & constrained
  21. //  07/17/97    CAR marked fields transient as needed
  22. //                  implemented readObject to create Audio streams after deserialization
  23. //  07/17/97    LAB Layed out the code in accordance to the Good Bean Spec.  Updated version tag
  24. //                    to 1.1.
  25. //  08/19/97    CAR changed getURLList to use the new URLlist vector
  26.  
  27. /**
  28.  * SoundPlayer component.
  29.  * This component allows the playing of a list of sound clips
  30.  * either serially or simultaneously. The sound information is
  31.  * 8-bit 8000hz u-law encoded data.
  32.  *
  33.  * @version 1.1, July 25, 1997
  34.  * @author Symantec
  35.  */
  36. public class SoundPlayer implements java.io.Serializable
  37. {
  38.     /**
  39.      * A constant specifying that the sound should run forever.
  40.      * Use with setRepeat().
  41.      * @see #setRepeat
  42.      */
  43.     public static final int INFINITE = -1;
  44.  
  45.     /**
  46.      * Constructs a SoundPlayer.
  47.      * By default the sound clips will play serially (sync mode true),
  48.      * and will play only once (repeat count == 1).
  49.      */
  50.     public SoundPlayer()
  51.     {
  52.         clips = new Vector();
  53.         URLlist = new Vector();
  54.     }
  55.  
  56.     /**
  57.      * Sets whether to play the sound clips one after the other,
  58.      * or all simultaneously.
  59.      *
  60.      * @param newSyncMode true to play the sound clips serially,
  61.      * false to play them all simultaneously
  62.      *
  63.      * @exception PropertyVetoException
  64.      * if the specified property value is unacceptable
  65.      */
  66.     public void setSyncMode(boolean newSyncMode) throws PropertyVetoException
  67.     {
  68.         if (sync != newSyncMode)
  69.         {
  70.             Boolean oldSyncModeBoolean = new Boolean(sync);
  71.             Boolean newSyncModeBoolean = new Boolean(newSyncMode);
  72.  
  73.             vetos.fireVetoableChange("SyncMode", oldSyncModeBoolean, newSyncModeBoolean);
  74.  
  75.             sync = newSyncMode;
  76.             if (spt != null)
  77.                 spt.doSync(newSyncMode);
  78.  
  79.             changes.firePropertyChange("SyncMode", oldSyncModeBoolean, newSyncModeBoolean);
  80.         }
  81.     }
  82.  
  83.     /**
  84.      * Returns the number of times the list of sound clips is played.
  85.      */
  86.     public boolean isSyncMode()
  87.     {
  88.         return sync;
  89.     }
  90.  
  91.     /**
  92.      * @deprecated
  93.      * @see #isSyncMode
  94.      */
  95.     public boolean getSyncMode()
  96.     {
  97.         return isSyncMode();
  98.     }
  99.  
  100.      /**
  101.      * Sets the number of times the list of sound clips is played.
  102.      *
  103.      * @param c the number of times to play the list of sound clips,
  104.      * or INFINITE to keep playing forever
  105.      * @see #getRepeat
  106.      *
  107.      * @exception PropertyVetoException
  108.      * if the specified property value is unacceptable
  109.      */
  110.     public void setRepeat(int c) throws PropertyVetoException
  111.     {
  112.         if (repeatCt != c)
  113.         {
  114.             Integer newValue = new Integer(c);
  115.             Integer oldValue = new Integer(repeatCt);
  116.  
  117.             vetos.fireVetoableChange("Repeat", oldValue, newValue);
  118.  
  119.             repeatCt = c;
  120.  
  121.             changes.firePropertyChange("Repeat", oldValue, newValue);
  122.         }
  123.     }
  124.  
  125.     /**
  126.      * Gets the number of times the list of sound clips is played.
  127.      * @see #setRepeat(int)
  128.      */
  129.     public int getRepeat()
  130.     {
  131.         return repeatCt;
  132.     }
  133.  
  134.     /**
  135.      * Initializes the list of sound clips using the given list of sound clip
  136.      * data URLs. Any previously existing sound clip information is lost.
  137.      * The files specified by the URLs contain u-law encoded 8-bit 8000hz data.
  138.      * @param list a list of URLs of files containing sound clip data
  139.      * @see #getURLList
  140.      *
  141.      * @exception PropertyVetoException
  142.      * if the specified property value is unacceptable
  143.      */
  144.     public void setURLList(URL[] list) throws PropertyVetoException
  145.     {
  146.         clips.removeAllElements();
  147.         URLlist.removeAllElements();
  148.  
  149.         URL[] oldValue = getURLList();
  150.  
  151.         vetos.fireVetoableChange("URLList", oldValue, list);
  152.  
  153.         for (int i = 0; i < list.length; ++i)
  154.             addURL(list[i]);
  155.  
  156.         changes.firePropertyChange("URLList", oldValue, list);
  157.     }
  158.  
  159.      /**
  160.      * Gets the URL of each sound clip.
  161.      * @see #setURLList
  162.      */
  163.     public URL[] getURLList()
  164.     {
  165.         /*
  166.         int len = clips.size();
  167.         URL[] ret = new URL[len];
  168.         for (int i = 0; i < len; ++i)
  169.             ret[i] = (URL)clips.elementAt(i);
  170.         */
  171.  
  172.         URL[] ret = new URL[URLlist.size()];
  173.         URLlist.copyInto(ret);
  174.  
  175.         return ret;
  176.     }
  177.  
  178.     //
  179.     // Methods
  180.     //
  181.  
  182.     /**
  183.      * Appends the sound clip data at the specified URL to the current list
  184.      * of sound clips.
  185.      * The specified file contains u-law encoded 8-bit 8000hz data.
  186.      * @param u the URL of a file containing sound clip data
  187.      */
  188.     public void addURL(URL u)
  189.     {
  190.         InputStream in = null;
  191.         AudioData data;
  192.         try
  193.         {
  194.             try
  195.             {
  196.                 URLConnection uc = u.openConnection();
  197.                 uc.setAllowUserInteraction(true);
  198.                 in = uc.getInputStream();
  199.                 AudioStream as = new AudioStream(in);
  200.                 clips.addElement(new SoundViewerItem(as.getData(),
  201.                     (int)(((double)as.getLength() / 7168.0) * 1000.0)));
  202.                 URLlist.addElement(u);
  203.             }
  204.             finally
  205.             {
  206.                 if (in != null)
  207.                     in.close();
  208.             }
  209.         }
  210.         catch (IOException e) { }
  211.     }
  212.  
  213.     /**
  214.      * Appends the sound clip data at the specified URL to the current list
  215.      * of sound clips.
  216.      * The specified file contains u-law encoded 8-bit 8000hz data.
  217.      * @param url the URL of a file containing sound clip data
  218.      */
  219.     public void addStringURL(String url)
  220.     {
  221.         try
  222.         {
  223.             addURL(new URL(url));
  224.         }
  225.         catch (MalformedURLException e) {}
  226.     }
  227.  
  228.     /**
  229.      * Starts playing the sound clips.
  230.      */
  231.     public void play()
  232.     {
  233.         spt = new SoundViewerThread(clips, sync, repeatCt);
  234.         spt.start();
  235.     }
  236.  
  237.     /**
  238.      * Immediately stops the playing of sound clips.
  239.      */
  240.     public void stop()
  241.     {
  242.         if (spt != null)
  243.             spt.doStop();
  244.     }
  245.  
  246.     /**
  247.      * Stops the playing of sound clips after the specified number of
  248.      * milliseconds.
  249.      * @param #delay the number of milliseconds to wait before stopping
  250.      * sound play
  251.      */
  252.     public void stop(int delay)
  253.     {
  254.         try
  255.         {
  256.             Thread.sleep(delay);
  257.         }
  258.         catch (InterruptedException ie) {}
  259.         stop();
  260.     }
  261.  
  262.     /**
  263.      * Adds a listener for all event changes.
  264.      * @param PropertyChangeListener listener the listener to add.
  265.      * @see #removePropertyChangeListener
  266.      */
  267.     public void addPropertyChangeListener(PropertyChangeListener listener)
  268.     {
  269.         //super.addPropertyChangeListener(listener);
  270.         changes.addPropertyChangeListener(listener);
  271.     }
  272.  
  273.     /**
  274.      * Removes a listener for all event changes.
  275.      * @param PropertyChangeListener listener the listener to remove.
  276.      * @see #addPropertyChangeListener
  277.      */
  278.     public void removePropertyChangeListener(PropertyChangeListener listener)
  279.     {
  280.         //super.removePropertyChangeListener(listener);
  281.         changes.removePropertyChangeListener(listener);
  282.     }
  283.  
  284.     /**
  285.      * Adds a vetoable listener for all event changes.
  286.      * @param VetoableChangeListener listener the listener to add.
  287.      * @see #removeVetoableChangeListener
  288.      */
  289.     public void addVetoableChangeListener(VetoableChangeListener listener)
  290.     {
  291.          //super.addVetoableChangeListener(listener);
  292.         vetos.addVetoableChangeListener(listener);
  293.     }
  294.  
  295.     /**
  296.      * Removes a vetoable listener for all event changes.
  297.      * @param VetoableChangeListener listener the listener to remove.
  298.      * @see #addVetoableChangeListener
  299.      */
  300.     public void removeVetoableChangeListener(VetoableChangeListener listener)
  301.     {
  302.         //super.removeVetoableChangeListener(listener);
  303.         vetos.removeVetoableChangeListener(listener);
  304.     }
  305.  
  306.     private void readObject(java.io.ObjectInputStream stream) throws java.io.IOException, ClassNotFoundException
  307.     {
  308.         stream.defaultReadObject();
  309.  
  310.         clips = new Vector();
  311.         for (int i = 0; i < URLlist.size(); ++i)
  312.         {
  313.             InputStream in = null;
  314.             AudioData data;
  315.             try
  316.             {
  317.                 try
  318.                 {
  319.                     URLConnection uc = ((URL) URLlist.elementAt(i)).openConnection();
  320.                     uc.setAllowUserInteraction(true);
  321.                     in = uc.getInputStream();
  322.                     AudioStream as = new AudioStream(in);
  323.                     clips.addElement(new SoundViewerItem(as.getData(),
  324.                         (int)(((double)as.getLength() / 7168.0) * 1000.0)));
  325.                 }
  326.                 finally
  327.                 {
  328.                     if (in != null)
  329.                         in.close();
  330.                 }
  331.             } catch (IOException e) {}
  332.         }
  333.     }
  334.  
  335.     // Private members
  336.     transient private Vector clips;
  337.     transient private SoundViewerThread spt = null;
  338.     private Vector URLlist;
  339.     private boolean sync = true;
  340.     private int repeatCt = 1;
  341.  
  342.     private symantec.itools.beans.VetoableChangeSupport vetos = new symantec.itools.beans.VetoableChangeSupport(this);
  343.     private symantec.itools.beans.PropertyChangeSupport changes = new symantec.itools.beans.PropertyChangeSupport(this);
  344. }
  345.  
  346. class SoundViewerThread extends Thread
  347. {
  348.     SoundViewerThread(Vector clips, boolean sync, int rct)
  349.     {
  350.         this.clips = clips;
  351.         this.sync  = sync;
  352.         repeatCt   = rct;
  353.     }
  354.  
  355.     public void run()
  356.     {
  357.         while (repeatCt == -1 || repeatCt-- > 0)
  358.         {
  359.             int nClips = clips.size();
  360.             for (int index = 0; index < nClips && !doEnd; ++index)
  361.             {
  362.                 SoundViewerItem spi = (SoundViewerItem)clips.elementAt(index);
  363.                 curStream = new AudioDataStream(spi.data);
  364.                 AudioPlayer.player.start(curStream);
  365.                 if (sync)
  366.                 {
  367.                     try
  368.                     {
  369.                         Thread.sleep(spi.delay);
  370.                     }
  371.                     catch (InterruptedException ie) {}
  372.                 }
  373.             }
  374.             curStream = null;
  375.         }
  376.         doEnd = false;
  377.     }
  378.  
  379.     void doSync(boolean f)
  380.     {
  381.         sync = f;
  382.     }
  383.  
  384.     void doStop()
  385.     {
  386.         if (curStream != null)
  387.             AudioPlayer.player.stop(curStream);
  388.         doEnd = true;
  389.     }
  390.  
  391.     private Vector clips;
  392.     private boolean doEnd = false;
  393.     private AudioDataStream curStream = null;
  394.     private int repeatCt = 0;
  395.     private boolean sync = true;
  396. }
  397.  
  398. class SoundViewerItem
  399. {
  400.     SoundViewerItem(AudioData data, int delay)
  401.     {
  402.         this.data = data;
  403.         this.delay = delay;
  404.     }
  405.  
  406.     AudioData data;
  407.     int delay;
  408. }
  409.